<?php

declare(strict_types=1);

namespace App\Service;

use App\Exception\BusinessException;
use App\Lib\BaseValidator;
use App\Model\ArticleFavorite;
use App\Model\ArticleLike;
use App\Model\Articles;
use App\Repository\Article\ArticleRepository;
use Hyperf\Context\Context;
use Hyperf\DbConnection\Db;
use Hyperf\Di\Annotation\Inject;

class ArticleService
{
    #[Inject]
    protected ArticleRepository $articleRepository;

    /**
     * 文章列表
     * @param int $page
     * @param int $size
     * @param array $params
     * @return array
     */
    public function gerArticleList(int $page, int $size, array $params): array
    {
        $query = Articles::with(['tags', 'categories']);
        $filters = array_filter([
            'user_id' => $params['user_id'] ?? null,
            'title' => $params['title'] ?? null,
            'content' => $params['content'] ?? null,
            'tag' => $params['tag'] ?? null,
            'category' => $params['category'] ?? null,
            'status' => $params['status'] ?? null,
        ]);
        //应用筛选条件
        $this->applyFilters($query, $filters);
        //排序
        $query->orderBy('created_at', 'desc');
        $articles = $query->paginate($size, ['*'], 'page', $page);
        return [
            'articles' => $articles->items(),
            'pagination' => [
                'page' => $articles->currentPage(),
                'size' => $articles->perPage(),
                'total' => $articles->total(),
                'pages' => $articles->lastPage()
            ],
        ];
    }

    /**
     * 条件筛选
     * @param $query
     * @param array $filters
     * @return void
     */
    protected function applyFilters($query, array $filters): void
    {
        //筛选标题
        if(!empty($filters['title'])) {
            $query->where('title', 'like', "%{$filters['title']}%");
        }
        //筛选内容
        if(!empty($filters['content'])) {
            $query->where('content', 'like', "%{$filters['content']}%");
        }
        //筛选作者
        if(!empty($filters['user_id'])) {
            $query->where('user_id', $filters['user_id']);
        }
        //按标签筛选
        if(!empty($filters['tag'])) {
            $this->filterByTags($query, $filters['tag']);
        }
        //按分类筛选
        if(!empty($filters['category'])) {
            $this->filterByCategory($query, $filters['category']);
        }
        //按状态筛选
        if(!empty($filters['status'])) {
            $query->where('status', $filters['status']);
        }
    }

    /**
     * 标签筛选
     * @param $query
     * @param $tags
     * @return void
     */
    protected function filterByTags($query, $tags): void
    {
        if (is_array($tags)) {
            $tagIds = $tags;
        } else {
            $tagIds = explode(',', $tags);
        }

        $tagIds = array_map('intval', $tagIds);
        $tagIds = array_filter($tagIds);

        if (!empty($tagIds)) {
            $query->whereHas('tags', function ($q) use ($tagIds) {
                $q->whereIn('tag_id', $tagIds);
            });
        }
    }

    /**
     * 分类筛选
     * @param $query
     * @param $category
     * @return void
     */
    protected function filterByCategory($query, $category): void {
        if(is_array($category)) {
            $categoryIds = $category;
        } else {
            $categoryIds = explode(',', $category);
        }
        $categoryIds = array_map('intval', $categoryIds);
        $categoryIds = array_filter($categoryIds);
        if (!empty($categoryIds)) {
            $query->whereHas('categories', function ($q) use ($categoryIds) {
                $q->whereIn('category_id', $categoryIds);
            });
        }
    }



    /**
     * 创建文章
     * @param array $data
     * @return mixed
     * @throws \App\Lib\ValidateException
     */
    public function createArticle(array $data): mixed
    {
        //数据验证
        $this->validateArticleData($data);
        //获取用户id
        $userId = Context::get("login_user_id");
        $data['user_id'] = $userId;
        return Db::transaction(function () use ($data) {
            $tags = $data['tags'] ?? [];
            $categories = $data['categories'] ?? [];
            $article = $this->articleRepository->create($data);
            //处理标签
            if (!empty($tags)) {
                $article->tags()->sync($tags);
            }
            //处理分类
            if (!empty($categories)) {
                $article->categories()->sync($categories);
            }
            return $article->load(['tags']);
        });
    }

    /**
     * 更新文章
     * @param int $id
     * @param array $data
     * @return object
     * @throws \App\Lib\ValidateException
     */
    public function updateArticle(int $id, array $data): object
    {
        //数据验证
        $this->validateArticleData($data);
        //身份验证
        $userId = Context::get("login_user_id");
        $article = $this->articleRepository->getArticleDetailById($id);
        if($userId != $article->user_id) {
            throw new BusinessException('您无权修改他人的文章');
        }
        return Db::transaction(function () use ($id, $data, $article) {
            $tags = $data['tags'] ?? [];
            $categories = $data['categories'] ?? [];
            $article->update([
                'title' => $data['title'],
                'content' => $data['content'],
                'cover_image' => $data['cover_image']
            ]);
            //更新标签
            if (!empty($tags)) {
                $article->tags()->sync($tags);
            }
            //更新分类
            if (!empty($categories)) {
                $article->categories()->sync($categories);
            }
            return $article->load(['tags']);
        });
    }

    /**
     * 根据id获取文章详情
     * @param int $id
     * @return object
     */
    public function getArticleDetail(int $id): object
    {
        $article =  $this->articleRepository->getArticleDetailById($id);
        return $article->load(['tags', 'user']);
    }

    /**
     * 删除文章
     * @param int $id
     * @return bool|null
     * @throws \Exception
     */
    public function deleteArticle(int $id): ?bool
    {
        $article = $this->articleRepository->getArticleDetailById($id);
        return Db::transaction(function () use ($article) {
            //删除关联的标签
            $article->tags()->detach();
            //删除文章
            return $article->delete();
        });
    }

    /**
     * 点赞/取消点赞
     * @param int $id
     * @return array
     */
    public function likeArticle(int $id): array
    {
        $userId = Context::get("login_user_id");
        return Db::transaction(function () use ($userId, $id) {
            $article = $this->articleRepository->getArticleDetailById($id);
            //检查是否点赞
            $likeExist = $article->isLikedByUser($userId);
            if($likeExist) {
                //取消点赞
                $article->likes()->where('user_id', $userId)->delete();
                //点赞数量减一
                $article->like_count -= 1;
                $liked = false;
                $msg = '取消点赞';
            }else{
                //创建点赞记录
                ArticleLike::create(['user_id' => $userId, 'article_id' => $article->id]);
                $article->like_count += 1;
                $liked = true;
                $msg = '点赞成功';
            }
            $article->save();
            return [
                'data' => [
                    'liked' => $liked,
                    'like_count' => $article->getLikesCount()
                ],
                'msg' => $msg
            ];
        });
    }


    /**
     * 收藏/取消收藏
     * @param int $id
     * @return array
     */
    public function favoriteArticle(int $id): array
    {
        $userId = Context::get("login_user_id");
        return Db::transaction(function () use ($userId, $id) {
            $article = $this->articleRepository->getArticleDetailById($id);
            //检查是否收藏
            $favoriteExist = $article->isFavoirtedByUser($userId);
            if($favoriteExist) {
                //取消收藏
                $article->favorites()->where('user_id', $userId)->delete();
                //收藏数量减一
                $article->favorite_count -= 1;
                $favorited = false;
                $msg = '取消收藏';
            }else{
                //创建收藏记录
                ArticleFavorite::create(['user_id' => $userId, 'article_id' => $article->id]);
                //收藏数量加1
                $article->favorite_count += 1;
                $favorited = true;
                $msg = '收藏成功';
            }
            $article->save();
            return [
                'data' => [
                    'favorited' => $favorited,
                    'favorite_count' => $article->getFavoritesCount()
                ],
                'msg' => $msg
            ];
        });
    }

    /**
     * 文章数据验证
     * @param array $data
     * @return void
     * @throws \App\Lib\ValidateException
     */
    private function validateArticleData(array $data): void
    {
        $validatorResult = BaseValidator::make($data, [
            'title' => 'required|string|min:2|max:255',
            'content' => 'required',
            'cover_image' => 'required',
        ], [
            'title.required' => '文章标题不能为空',
            'title.min' => '文章标题为2到255个字符',
            'title.max' => '文章标题为2到255个字符',
            'content.required' => '文章内容不能为空',
            'cover_image.required' => '文章封面不能为空',
        ]);
        if (!$validatorResult) {
            throw new BusinessException(\App\Lib\BaseValidator::$error, 0);
        }
    }
}